﻿#pragma warning(disable: 4996)
#pragma warning(disable: 6031)

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <assert.h>

using namespace std;

void T_parameters_test();
void SmallBoxGirder_parameters_test();
void LargeBoxGirder_parameters_test();
void DoubleColumnPier_parameters_test();

typedef double Real;

/*
 *
 * 工具函数
 *
 */

const Real PI = 3.141592653589793;
const Real PI_180 = PI / 180;

Real Degree(Real radian)
{
	return radian / PI_180;
}

bool real_eq(Real a, Real b) {
	return abs(a - b) < 0.0001;
}

/*
 *
 * T梁专业参数转模型参数
 *
 */

 // BriX参数
struct T_BriX_parameters {
	Real L0;
	Real L1;
	Real L2;
	Real L3;
	Real L4;
	Real L5;
	Real L6;
	Real L7;
	Real S1;
	Real S2;
	int n;				// 片数
	Real d;				// 跨径
};

// 专业参数
struct T_professional_parameters {
	Real wu;			// 中跨梁宽
	Real H;				// 梁高
	Real h1;			// 梁顶板边厚
	Real h2;			// 梁顶板中厚
	Real h3;			// 马蹄上部高
	Real h4;			// 马蹄下部高
	Real wb;			// 马蹄底部宽
	Real w2;			// 翼板斜坡宽
	Real w3;			// 腹板厚
	Real w4;			// 悬挑宽
	Real L;				// 跨径
	int n;				// 梁片数
	Real D;				// 梁间距
	Real dw;			// 边跨梁宽 - 中跨梁宽（边跨梁与中跨梁宽之差）
	// 验证用(一些设计中,桥面宽不能通过梁尺寸直接计算)
	Real deck_width;	// 桥面宽(可能比梁宽更宽, 在一些设计中护栏有卡槽设计,所以dw不能简单的得到)
};

// 专业参数转BriX模型参数
void T_beam_parameters_convert(const T_professional_parameters& input, T_BriX_parameters& model)
{
	Real w_wetjoint = input.D - input.wu;							// 湿接缝宽 [=D-wu]

	model.L0 = input.w3;											// 肋板厚
	model.L1 = (input.wb - input.w3) / 2;							// (牛腿宽-肋板厚)/2
	model.L2 = input.h4;											// 马蹄下部高
	model.L3 = input.H - input.h2;									// 梁高-H2
	model.L4 = sqrt(pow(input.h2 - input.h1, 2) + pow(input.w2, 2));// sqrt((H2-H1)^2+w2^2)
	model.L5 = input.D - 2 * input.w2 - input.w3;					// 梁间距 -2 * w2 - w3
	model.L6 = (model.L5 - w_wetjoint) / 2 + input.dw;				// 边板悬挑宽
	model.L7 = input.h1;											// 梁顶板边厚
	model.S1 = Degree(atan(2 * input.h3 / (input.wb - input.w3)));	// atan(2*h3/(wb-w3))
	model.S2 = Degree(atan((input.h2 - input.h1) / input.w2));		// atan((H2-H1)/w2)
	model.n = input.n;
	model.d = input.L * 1000;
}

/*
 *
 * 小箱梁专业参数转模型参数
 *
 */

 // BriX参数
struct SmallBoxGirder_BriX_parameters {
	Real L0;
	Real L1;
	Real L2;
	Real L3;
	Real L4;
	Real L5;
	Real S1;
	Real S2;
	Real S3;
	int n;				// 片数
	Real d;				// 跨径
};

// 专业参数
struct SmallBoxGirder_professional_parameters {
	// 输入参数
	Real w;				// 梁宽
	Real H;				// 梁高
	Real h1;			// 梁顶板边厚
	Real h2;			// 梁顶板中厚
	Real n1;			// 腹板高宽比(n:1)
	Real wb;			// 底宽(底部圆角部分取直线交点)
	Real w1;			// 顶板外部倒角宽
	Real L;				// 跨径
	int n;				// 片数
	Real D;				// 梁间距
	Real dw;			// 边跨梁宽 - 中跨梁宽（边跨梁与中跨梁宽之差）
	// 中间计算用参数
	Real h3;			// 倒角高 [ = h2 - h1]
	Real h4;			// 腹板高 [ = H - h2]
	Real deck_width;	// 桥面宽 [=(片数-1)*梁间距+We*2]
	Real w_wetjoint;	// 湿接缝宽 [=D-w]
	Real w2;			// 腹板外侧宽 [=腹板高/n1]
	Real we;			// 边板外侧翼板宽度 [=dw+w/2-w2-wb/2]
};

void SmallBoxGirder_params_update(SmallBoxGirder_professional_parameters& params)
{
	params.we = (params.w - params.wb) / 2 - params.w2 + params.dw;
	params.h3 = params.h2 - params.h1;
	params.h4 = params.H - params.h2;
	params.deck_width = (params.n - 1) * params.D + params.we * 2;
	params.w_wetjoint = params.D - params.w;
	params.w2 = params.h4 / params.n1;
}

// 专业参数转BriX模型参数
void SmallBoxGirder_parameters_convert(const SmallBoxGirder_professional_parameters& input, SmallBoxGirder_BriX_parameters& model)
{
	model.L0 = input.wb;											// 底板宽
	model.L1 = sqrt(input.w2 * input.w2 + input.h4 * input.h4);		// 腹板斜长 sqrt(w2^2+内高^2)
	model.L2 = sqrt(input.w1 * input.w1 + input.h3 * input.h3);		// 倒角斜长 sqrt(h3^2+w1^2)
	model.L3 = input.D - input.wb - (input.w1 + input.w2) * 2;		// 梁间距-wb-(w1+w2)*2
	model.L4 = sqrt(input.we * input.we + input.h3 * input.h3);		// 边板外侧翼板斜长 sqrt(we^2+h3^2)
	model.L5 = input.h1;											// 项板边厚
	model.S1 = Degree(atan(input.n1));								// atan(n1)
	model.S2 = Degree(atan(input.h3 / input.w1));					// atan(h3/w1)
	model.S3 = Degree(atan(input.h3 / input.we));					// atan(h3/we))
	model.n = input.n;
	model.d = input.L * 1000;
}

/*
 *
 * 大箱梁专业参数转模型参数
 *
 */

 // BriX参数
struct LargeBoxGirder_BriX_parameters {
	Real L0;
	Real L1;
	Real L2;
	Real L3;
	Real S1;
	Real S2;
	Real d;				// 跨径
};

// 专业参数
struct LargeBoxGirder_professional_parameters {
	// 输入参数
	Real w;				// 梁宽
	Real H;				// 梁总高
	Real h1;			// 梁顶板边厚
	Real h3;			// 腹板高
	Real wb;			// 底宽(底部圆角部分取直线交点)
	Real w1;			// 翼板宽
	Real L;				// 跨径
	// 计算参数
	Real h2;			// 翼板高 H-h1-h3
	Real w2;			// 腹板宽 (w-wb)/2-w1
};

void LargeBoxGirder_params_update(LargeBoxGirder_professional_parameters& params)
{
	params.h2 = params.H - params.h1 - params.h3;
	params.w2 = (params.w - params.wb) / 2 - params.w1;
}

// 专业参数转BriX模型参数
void LargeBoxGirder_parameters_convert(const LargeBoxGirder_professional_parameters& input, LargeBoxGirder_BriX_parameters& model)
{
	model.L0 = input.wb;											// 底板宽
	model.L1 = sqrt(input.w2 * input.w2 + input.h3 * input.h3);		// 腹板斜长 sqrt(h3^2+w2^2)
	model.L2 = sqrt(input.w1 * input.w1 + input.h2 * input.h2);		// 翼板斜长 sqrt(h2^2+w1^2)
	model.L3 = input.h1;											// 梁顶板边厚 h1
	if (real_eq(input.w2, 0))
		model.S1 = 90;
	else
		model.S1 = Degree(atan(input.h3/input.w2));					// 腹板角度 atan(h1/w2)
	model.S2 = Degree(atan(input.h2 / input.w1));					// 翼板角度 atan(h2/w1)
	model.d = input.L * 1000;
}

/*
 *
 * 双柱式桥墩专业参数转模型参数
 *
 */

 // BriX参数
struct DoubleColumnPier_BriX_parameters {
	Real L0;
	Real L1;
	Real L2;
	Real L3;
	Real L4;
	Real L5;
	Real L6;
	Real L7;
	Real L8;
	Real L9;
	Real L10;
	Real L11;
	Real S0;
	Real S1;
	Real d;				// 跨径
};

// 专业参数
struct DoubleColumnPier_professional_parameters {
	Real w;	    // 盖梁宽
	Real H;	    // 盖梁高
	Real thick;	// 盖梁厚
	Real h1;    // 盖梁上部高
	Real h2;    // 盖梁下部高
	Real he1;	// 挡块高
	Real we1;	// 挡块上部宽
	Real we2;	// 挡块下部宽
	Real wb;	// 底宽
	Real w1;	// 盖梁下部斜坡宽
	Real w2;	// 挡块至盖梁边距
	Real w3;	// 立柱至盖梁底外侧的距离
	Real LP;	// 立柱长度
	Real dp;	// 立柱直径
	Real d1;	// 上部梁体距挡块距离
	Real d2;	// 上部梁体距盖梁高度
	Real L;		// 跨径
};

// 专业参数转BriX模型参数
// txl_l1: 对于T形梁, 需要输入l1参数, 对于其它梁体为0;
void DoubleColumnPier_parameters_convert(const DoubleColumnPier_professional_parameters& input, DoubleColumnPier_BriX_parameters& model, Real txl_l1)
{
	model.L0 = input.wb;											// 底宽
	model.L1 = sqrt(input.w1 * input.w1 + input.h2 * input.h2);		// 下部斜长 sqrt(h2^2+w1^2)
	model.L2 = input.h1 + input.he1;								// 盖梁侧面高 h1+he1
	model.L3 = input.we1;											// 挡块上宽 we1
	model.L4 = sqrt(pow(input.we2 - input.we1, 2) + input.he1 * input.he1);		// 挡块斜长 sqrt((we2-we1)^2+he1^2)
	model.L5 = input.thick;											// 盖梁桥长方向厚度
	model.L6 = input.d1 + txl_l1;									// d1+txl.l1(除T梁外的其它梁为txl.l1=0)
	model.L7 = input.dp / 2 + input.w3;								// 立柱直径/2+w3
	model.L8 = input.d2;											// 上部结构梁体距盖梁高度
	model.L9 = input.w - (input.w2 + input.we1) * 2;				// 盖梁顶除去挡块的长度
	model.L10 = input.dp;											// 立柱直径
	model.L11 = input.LP;											// 立柱长度

	model.S0 = Degree(atan(input.h2 / input.w1));					// 盖梁下部斜坡角度
	model.S1 = 90-Degree(atan((input.we2-input.we1) / input.he1));	// 盖梁下部斜坡角度

	model.d = input.L;
}

/**************************************************************************************************************************
 *
 * 测试函数
 *
 **************************************************************************************************************************
 */

void dump_T_BriX_parameters(const T_BriX_parameters& params);
void check_T_BriX_parameters(const T_BriX_parameters& params);

void T_parameters_test()
{
	auto fp = freopen("D:/Temp/参数测试数据表(T梁).txt", "r", stdin);
	Real temp;
	T_professional_parameters a = { 0 };
	T_BriX_parameters b = { 0 };
	int n;
	cin >> n;
	for (int i = 0; i < n; ++i) {
		cin >> a.L
			>> a.H
			>> a.deck_width
			>> temp
			>> a.n
			>> a.D
			>> a.h1
			>> a.wb
			>> a.wu
			>> a.w2
			>> a.w3
			>> a.w4
			>> a.dw
			>> a.h2
			>> a.h3
			>> a.h4;
		T_beam_parameters_convert(a, b);
		check_T_BriX_parameters(b);
		//dump_T_BriX_parameters(b);
	}
	fclose(fp);
}

void check_T_BriX_parameters(const T_BriX_parameters& params)
{
	//dump_T_BriX_parameters(params);
	Real L0, L1, L2, L3, L4, L5, L6, L7, S1, S2;
	cin >> L0
		>> L1
		>> L2
		>> L3
		>> L4
		>> L5
		>> L6
		>> L7
		>> S1
		>> S2;
	assert(real_eq(L0, params.L0));
	assert(real_eq(L1, params.L1));
	assert(real_eq(L2, params.L2));
	assert(real_eq(L3, params.L3));
	assert(real_eq(L4, params.L4));
	assert(real_eq(L5, params.L5));
	assert(real_eq(L6, params.L6));
	assert(real_eq(L7, params.L7));
	assert(real_eq(S1, params.S1));
	assert(real_eq(S2, params.S2));
	//printf("n = %d\n", params.n);
	//printf("d = %.3f\n", params.d);
}

void dump_T_BriX_parameters(const T_BriX_parameters& params)
{
	printf("L0 = %.3f\n", params.L0);
	printf("L1 = %.3f\n", params.L1);
	printf("L2 = %.3f\n", params.L2);
	printf("L3 = %.3f\n", params.L3);
	printf("L4 = %.3f\n", params.L4);
	printf("L5 = %.3f\n", params.L5);
	printf("L6 = %.3f\n", params.L6);
	printf("L7 = %.3f\n", params.L7);
	printf("S1 = %.3f\n", params.S1);
	printf("S2 = %.3f\n", params.S2);
	printf("n = %d\n", params.n);
	printf("d = %.3f\n", params.d);
}

void dump_SmallBoxGirder_BriX_parameters(const SmallBoxGirder_BriX_parameters& params);
void check_SmallBoxGirder_BriX_parameters(const SmallBoxGirder_BriX_parameters& params);

void SmallBoxGirder_parameters_test()
{
	auto fp = freopen("D:/Temp/参数测试数据表(小箱梁).txt", "r", stdin);
	Real temp;
	SmallBoxGirder_professional_parameters a = { 0 };
	SmallBoxGirder_BriX_parameters b = { 0 };
	int n;
	cin >> n;
	for (int i = 0; i < n; ++i) {
		cin >> a.L
			>> a.H
			>> a.h1
			>> a.h4
			>> a.h2
			>> a.h3
			>> a.deck_width
			>> a.n
			>> a.D
			>> a.w_wetjoint
			>> a.w
			>> a.wb
			>> a.w1
			>> a.w2
			>> a.we
			>> a.dw
			>> a.n1;
		SmallBoxGirder_params_update(a);
		SmallBoxGirder_parameters_convert(a, b);
		check_SmallBoxGirder_BriX_parameters(b);
	}
	fclose(fp);
}

void check_SmallBoxGirder_BriX_parameters(const SmallBoxGirder_BriX_parameters& params)
{
	//dump_SmallBoxGirder_BriX_parameters(params);
	Real L0, L1, L2, L3, L4, L5, L6, L7, S1, S2, S3;
	cin >> L0
		>> L1
		>> L2
		>> L3
		>> L4
		>> L5
		>> S1
		>> S2
		>> S3;
	assert(real_eq(L0, params.L0));
	assert(real_eq(L1, params.L1));
	assert(real_eq(L2, params.L2));
	assert(real_eq(L3, params.L3));
	assert(real_eq(L4, params.L4));
	assert(real_eq(L5, params.L5));
	assert(real_eq(S1, params.S1));
	assert(real_eq(S2, params.S2));
	assert(real_eq(S3, params.S3));
}


void dump_SmallBoxGirder_BriX_parameters(const SmallBoxGirder_BriX_parameters& params)
{
	printf("L0 = %.3f\n", params.L0);
	printf("L1 = %.3f\n", params.L1);
	printf("L2 = %.3f\n", params.L2);
	printf("L3 = %.3f\n", params.L3);
	printf("L4 = %.3f\n", params.L4);
	printf("L5 = %.3f\n", params.L5);
	printf("S1 = %.3f\n", params.S1);
	printf("S2 = %.3f\n", params.S2);
	printf("S3 = %.3f\n", params.S3);
	printf("n = %d\n", params.n);
	printf("d = %.3f\n", params.d);
}

void dump_LargeBoxGirder_BriX_parameters(const LargeBoxGirder_BriX_parameters& params);
void check_LargeBoxGirder_BriX_parameters(const LargeBoxGirder_BriX_parameters& params);

void LargeBoxGirder_parameters_test()
{
	auto fp = freopen("D:/Temp/参数测试数据表(大箱梁).txt", "r", stdin);
	Real temp;
	LargeBoxGirder_professional_parameters a = { 0 };
	LargeBoxGirder_BriX_parameters b = { 0 };
	int n;
	cin >> n;
	for (int i = 0; i < n; ++i) {
		cin >> a.L
			>> a.w
			>> a.wb
			>> a.H
			>> a.w1
			>> a.h1
			>> a.h2
			>> a.h3
			>> temp
			>> temp;
		LargeBoxGirder_params_update(a);
		LargeBoxGirder_parameters_convert(a, b);
		check_LargeBoxGirder_BriX_parameters(b);
	}
	fclose(fp);
}

void check_LargeBoxGirder_BriX_parameters(const LargeBoxGirder_BriX_parameters& params)
{
	//dump_LargeBoxGirder_BriX_parameters(params);
	Real L0, L1, L2, L3, L4, L5, L6, L7, S1, S2, S3;
	cin >> L0
		>> L1
		>> L2
		>> L3
		>> S1
		>> S2;
	assert(real_eq(L0, params.L0));
	assert(real_eq(L1, params.L1));
	assert(real_eq(L2, params.L2));
	assert(real_eq(L3, params.L3));
	assert(real_eq(S1, params.S1));
	assert(real_eq(S2, params.S2));
}


void dump_LargeBoxGirder_BriX_parameters(const LargeBoxGirder_BriX_parameters& params)
{
	printf("L0 = %.3f\n", params.L0);
	printf("L1 = %.3f\n", params.L1);
	printf("L2 = %.3f\n", params.L2);
	printf("L3 = %.3f\n", params.L3);
	printf("S1 = %.3f\n", params.S1);
	printf("S2 = %.3f\n", params.S2);
	printf("d = %.3f\n", params.d);
}

void dump_DoubleColumnPier_BriX_parameters(const DoubleColumnPier_BriX_parameters& params);
void check_DoubleColumnPier_BriX_parameters(const DoubleColumnPier_BriX_parameters& params);

void DoubleColumnPier_parameters_test()
{
	auto fp = freopen("D:/Temp/参数测试数据表(双柱式桥墩).txt", "r", stdin);
	Real temp;
	DoubleColumnPier_professional_parameters a = { 0 };
	DoubleColumnPier_BriX_parameters b = { 0 };
	int n;
	Real txl_l1;
	cin >> n;
	for (int i = 0; i < n; ++i) {
		cin >> a.L
			>> a.thick
			>> a.w
			>> a.H
			>> a.LP
			>> a.dp
			>> a.d1
			>> a.d2
			>> a.w1
			>> a.wb
			>> a.w2
			>> a.w3
			>> a.h1
			>> a.h2
			>> a.he1
			>> a.we1
			>> txl_l1
			>> temp;
		a.we2 = a.we1;
		DoubleColumnPier_parameters_convert(a, b, txl_l1);
		check_DoubleColumnPier_BriX_parameters(b);
	}
	fclose(fp);
}

void check_DoubleColumnPier_BriX_parameters(const DoubleColumnPier_BriX_parameters& params)
{
	//dump_DoubleColumnPier_BriX_parameters(params);
	Real L0, L1, L2, L3, L4, L5, L6, L7, L8, L9, L10,L11, S0, S1, S2, S3, temp;
	cin >> L0
		>> L1
		>> L2
		>> L3
		>> L4
		>> L5
		>> L6
		>> L7
		>> L8
		>> L9
		>> L10
		>> L11
		>> S0
		>> S1
		>> temp;
	assert(real_eq(L0, params.L0));
	assert(real_eq(L1, params.L1));
	assert(real_eq(L2, params.L2));
	assert(real_eq(L3, params.L3));
	assert(real_eq(L4, params.L4));
	assert(real_eq(L5, params.L5));
	assert(real_eq(L6, params.L6));
	assert(real_eq(L7, params.L7));
	assert(real_eq(L8, params.L8));
	assert(real_eq(L9, params.L9));
	assert(real_eq(L10, params.L10));
	assert(real_eq(L11, params.L11));
	assert(real_eq(S0, params.S0));
	assert(real_eq(S1, params.S1));
}


void dump_DoubleColumnPier_BriX_parameters(const DoubleColumnPier_BriX_parameters& params)
{
	printf("L0 = %.3f\n", params.L0);
	printf("L1 = %.3f\n", params.L1);
	printf("L2 = %.3f\n", params.L2);
	printf("L3 = %.3f\n", params.L3);
	printf("S0 = %.3f\n", params.S0);
	printf("S1 = %.3f\n", params.S1);
	printf("d = %.3f\n", params.d);
}

int main()
{
	T_parameters_test();
	SmallBoxGirder_parameters_test();
	LargeBoxGirder_parameters_test();
	DoubleColumnPier_parameters_test();
	return 0;
}